#include "base/log.h"
#include "base/logstream.h"

#include <unistd.h>
#include <sys/syscall.h>

#include "base/thread.h"

namespace net_tools::base{
namespace detail{

class Thread_main : net_tools::base::noncopyable{
 public:
  Thread_main(func thread_begin_call,
              Count_down_cond* Count_cond,
              std::string* thread_name)
  :thread_begin_call_(std::move(thread_begin_call)),
   Count_cond_(Count_cond),
   thread_name_(thread_name)
  {
  };
  void Start(){
    base::Thread::InitThreadtid();
    base::Thread::InitThreadname(thread_name_);
    net_tools::Log::logstream_ = new net_tools::base::Logstream((int)syscall(SYS_gettid));
    NT_LOG_TRACE << "THREAD CREAT NAME:" << *thread_name_ << NT_LOG_ENDL;
    Count_cond_->Signal();
    thread_begin_call_();
  };
 private:
  func thread_begin_call_;
  Count_down_cond *Count_cond_;
  std::string* thread_name_;
};

} // namespace detail

__thread unsigned int Thread::thread_tid_ = 0;
__thread std::string* Thread::p_thread_name_ = nullptr;

void* Start_thread(void* obj){
  detail::Thread_main* Thread_main_ = reinterpret_cast<detail::Thread_main*>(obj);
  Thread_main_->Start();
  delete Thread_main_;
  return nullptr;
};

Thread::Thread(func thread_begin_call,std::string thread_name)
  :threadid_(0),
   thread_begin_call_(std::move(thread_begin_call)),
   Count_cond_(1),
   thread_name_(new std::string(thread_name))
{
};

void Thread::Start(){
  detail::Thread_main *thread_main_ = new detail::Thread_main(std::move(thread_begin_call_),&Count_cond_,thread_name_);
  pthread_create(&threadid_,
                  NULL,
                  &Start_thread,
                  thread_main_
                 );
  Count_cond_.Wait();
};

void Thread::InitThreadtid(){
  thread_tid_ = syscall(SYS_gettid);
};
void Thread::InitThreadname(std::string* thread_name){
  p_thread_name_ = thread_name;
};

} //namespace net_tools::base